﻿using Me.Framework.Xml.Base;
using Me.Framework.Xml.XmlAttr;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Me.Framework.Xml.DeConvert
{
    public class ObjToXml : XmlHelper
    {
        /// <summary>
        /// Convert Object To Xml
        /// </summary>
        /// <typeparam name="T">Class</typeparam>
        /// <param name="obj">Ojbect Val</param>
        /// <returns>Xml String</returns>
        public string ToXml<T>(T obj)
        {
            string xml = null;
            //判断是集合还是对象
            Type type = typeof(T);
            if (CheckIsCollection(type))
            {
                //集合
                IEnumerable collection = obj as IEnumerable;
                foreach (var item in collection)
                {
                    xml += ObjToXmlNode(item);
                }
            }
            else
            {
                //对象
                xml = ObjToXmlNode(obj);
            }

            return xml;
        }

        public string ObjToXmlNode(object obj)
        {
            //获取节点名
            Type type = obj.GetType();
            string nodeName = GetNodeName(type);
            string attr = null;
            StringBuilder xml = new StringBuilder();
            //获取属性
            PropertyInfo[] propertys = type.GetProperties();
            foreach (var property in propertys)
            {
                //判断是否是属性
                if (CheckIsAttribute(property))
                {
                    attr += GetAttributeVal(property,obj);
                }
                else
                {
                    //节点
                    xml.Append(GetNode(property,obj));
                }
            }

            //string temp = xml.ToString();
            //string beginTag = BeginTag(nodeName, attr);
            //string closeTag = CloseTag(nodeName);
            //temp = temp.Insert(0,beginTag);
            //temp = temp + closeTag;

            string resutlXml = xml.ToString().Insert(0, BeginTag(nodeName, attr)) + CloseTag(nodeName);
            return resutlXml;
        }

        private string GetAttributeVal(PropertyInfo property, object obj)
        {
            //属性  获取属性名称
            string attrName = GetNodeAttrName<NodeAttrAttribute>(property, "Name");
            if (attrName == null)
                throw new Exception("节点属性配置错误,请检查配置");
            object attrVal = property.GetValue(obj);
            if (attrVal == null)
                attrVal = "";
            string result = attrName + "=\"" + attrVal + "\"";
            return result;
        }

        private string GetNode(PropertyInfo property,object obj) 
        {
            string node = null;
            if (CheckIsSysType(property.PropertyType))
            {
                string nodeName = GetNodeAttrName<NodeNameAttribute>(property, "Name");
                if (nodeName == null)
                    nodeName = property.Name;
                //系统类型 单节点
                node = GetSingleNode(property,obj,nodeName);
            }
            else
            {
                //对象、集合
                node = GetObjectNode(property,obj);
            }

            return node;
        }

        private string GetObjectNode(PropertyInfo property, object obj)
        {
            StringBuilder xml = new StringBuilder();
            object val = property.GetValue(obj);
            if (CheckIsCollection(val))
            {
                //集合
                object collectionVal = property.GetValue(obj);
                xml.Append(CollectionToObj(collectionVal));
            }
            else
            {
                //对象
                xml.Append(ObjToXmlNode(val));
            }
            return xml.ToString();
        }

        private string CollectionToObj(object obj)
        {
            Type singleType = obj.GetType().GenericTypeArguments.FirstOrDefault();
            string nodeName = GetNodeAttrName<NodeNameAttribute>(singleType, "Name");
            if (nodeName == null)
                nodeName = singleType.Name;
            IEnumerable collection = obj as IEnumerable;
            StringBuilder xml = new StringBuilder();
            foreach (var item in collection)
            {
                string tempXml = null;
                if (CheckIsSysType(singleType))
                {
                    tempXml = BeginTag(nodeName) + item + CloseTag(nodeName);
                }
                else
                {
                    if (CheckIsCollection(singleType))
                    {
                        //集合
                        tempXml = CollectionToObj(item);
                    }
                    else
                    {
                        //对象
                        tempXml = ObjToXmlNode(item);
                    }
                }
                xml.Append(tempXml);
            }

            return xml.ToString();
        }

        private string GetSingleNode(PropertyInfo proerty, object obj, string nodeName)
        {
            string xml = BeginTag(nodeName) + proerty.GetValue(obj) + CloseTag(nodeName);
            return xml;
        }
    }
}
